<?php
/**
 * PHP Framework Core SOAP Serializer class
 *
 * @author Andrew <andrew@vitche.com>
 * @author Frozen Rain <frozenrain@mail.ru>
 **/
class SOAPSerializer {

    public static function fromResult($result) {

        if (is_object($result) && "stdClass" == get_class($result)) {

            if (SOAPSerializer::isTypedArray($result)) {

                // Typed array
                return SOAPSerializer::fromTypedArray($result);
            }

            // Apply naming convention to properties
            $fieldNames = array_keys((array)$result);
            foreach ($fieldNames as $fieldName) {
                $fieldValue = $result->$fieldName;
                unset($result->$fieldName);
                $fieldName = SOAPSerializer::fromKey($fieldName);
                $result->$fieldName = $fieldValue;
            }

            // Extract object fields which are hash tables
            // represented by the "KeyValueOfanyTypeanyType" type
            foreach ($result as $fieldName => $fieldValue) {
                if (isset($fieldValue->KeyValueOfanyTypeanyType)) {
                    $result->$fieldName = SOAPSerializer::fromKeyValue($fieldValue);
                }
            }
        }

        // Atomic type
        return $result;
    }

    private static function fromKeyValue($payload) {
        $result = array();
        $key = SOAPSerializer::fromKey($payload->KeyValueOfanyTypeanyType->Key);
        $value = $payload->KeyValueOfanyTypeanyType->Value;
        $result[$key] = $value;
        return $result;
    }

    private static function fromTypedArray($payload) {

        $payload = (array)$payload;

        // List payload types
        foreach ($payload as $payloadType => $payloadValue) {

            if (is_array($payloadValue)) {

                $result = array();

                // List payload items
                foreach ($payloadValue as $payloadItem) {

                    $payloadItem = (array)$payloadItem;

                    $object = new $payloadType();

                    // List array payload type field definitions
                    foreach ($payloadItem as $fieldName => $fieldValue) {

                        $fieldName = SOAPSerializer::fromKey($fieldName);

                        if (is_object($fieldValue)) {
                            $object->$fieldName = array_values((array)$fieldValue);
                        } else {
                            $object->$fieldName = $fieldValue;
                        }
                    }

                    // Extract object fields which are hash tables
                    // represented by the "KeyValueOfanyTypeanyType" type
                    foreach ($payloadItem as $fieldName => $fieldValue) {

                        if (isset($fieldValue->KeyValueOfanyTypeanyType)) {

                            $fieldName = SOAPSerializer::fromKey($fieldName);
                            $object->$fieldName = SOAPSerializer::fromKeyValue($fieldValue);
                        }
                    }

                    $result[] = $object;
                }

                return $result;
            }
        }
    }

    private static function fromKey($key) {

        $key = str_replace("_x003C_", "", $key);
        $key = str_replace("_x003E_k__BackingField", "", $key);
        return NamingConventionMapper::camelizeToOracle($key);
    }

    private static function isTypedArray($payload) {

        $payload = (array)$payload;

        // List payload types
        foreach ($payload as $payloadType => $payloadValue) {

            if (is_array($payloadValue)) {
                return true;
            }

            break;
        }

        return false;
    }
}
?>